package la.iok.hzsvn.lewin.movie.shopmovie.service;

import la.iok.hzsvn.lewin.movie.core.RoleEnum;
import la.iok.hzsvn.lewin.movie.core.Token;
import la.iok.hzsvn.lewin.movie.core.model.SimpleOrgUnitVo;
import la.iok.hzsvn.lewin.movie.core.model.SimpleUser;
import la.iok.hzsvn.lewin.movie.services.MovieServiceInvoker;
import la.iok.hzsvn.lewin.movie.services.OrgUnitIntegration;
import la.iok.hzsvn.lewin.movie.shopmovie.entity.Carpool;
import la.iok.hzsvn.lewin.movie.shopmovie.entity.Player;
import la.iok.hzsvn.lewin.movie.shopmovie.mapper.PlayerMapper;
import la.iok.hzsvn.lewin.movie.shopmovie.model.*;
import la.iok.hzsvn.lewin.mybatis.service.BaseServiceImpl;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.annotations.NotNullElement;
import la.iok.hzsvn.share.annotations.Nullable;
import la.iok.hzsvn.share.collection.IdOperators;
import la.iok.hzsvn.share.phone.PhoneNumberUtils;
import la.iok.hzsvn.share.utils.CollectionUtils;
import la.iok.hzsvn.share.utils.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class PlayerServiceImpl extends BaseServiceImpl<Player, PlayerMapper, Long> implements PlayerService {
    private final MovieServiceInvoker movieServiceInvoker;
    private final OrgUnitIntegration orgUnitIntegration;
    public PlayerServiceImpl(PlayerMapper mapper,
                             MovieServiceInvoker movieServiceInvoker,
                             OrgUnitIntegration orgUnitIntegration) {
        super(mapper);
        this.movieServiceInvoker = movieServiceInvoker;
        this.orgUnitIntegration = orgUnitIntegration;
    }

    @Override
    public List<Player> listOfCarpoolUsers(Collection<Long> carpoolIds, Collection<Long> userIds) {
        if(carpoolIds==null || userIds==null){
            return Collections.emptyList();
        }
        carpoolIds = carpoolIds.stream().filter(Objects::nonNull).collect(Collectors.toSet());
        userIds = userIds.stream().filter(Objects::nonNull).collect(Collectors.toSet());
        if(CollectionUtils.isEmpty(carpoolIds) || CollectionUtils.isEmpty(userIds)){
            return Collections.emptyList();
        }
        return mapper.listOfCarpoolUsers(carpoolIds, userIds);
    }

    @Override
    @NotNull
    @NotNullElement
    public List<Player> players(@Nullable Long carpoolId) {
        if(carpoolId == null){
            return Collections.emptyList();
        }
        return listByProperty("carpoolId", carpoolId);
    }

    @Override
    public Long save(Long userId, Long carpoolId, Long guideId) {
        Player entity = new Player();
        entity.setCarpoolId(carpoolId);
        entity.setUserId(userId);
        entity.setBelongId(guideId);
        entity.setJoinTime(new Date());
        entity.setGuideId(guideId);
        insertSelective(entity);
        return entity.getId();
    }

    @NotNull
    @NotNullElement
    @Override
    public List<PlayerVo> po2vo(@NotNull Carpool carpool, @NotNull @NotNullElement List<Player> list) {
        Set<Long> userIds = list.stream().map(Player::getBelongId).collect(Collectors.toSet());
        userIds.addAll(list.stream().map(Player::getUserId).collect(Collectors.toSet()));
        userIds.addAll(list.stream().map(Player::getGuideId).collect(Collectors.toSet()));
        List<SimpleUser> users = movieServiceInvoker.userInfo(userIds);
        return list.stream().map(item->{
            PlayerVo vo = new PlayerVo();
            BeanUtils.copyProperties(item, vo);
            SimpleUser user = IdOperators.find(users, item.getUserId());
            if(user != null){
                vo.setUserNickname(user.getNickname());
                vo.setUserPhoneNumber(PhoneNumberUtils.encPhoneNumber(user.getPhoneNumber()));
            }
            user = IdOperators.find(users, item.getBelongId());
            if(user != null){
                vo.setBelongNickname(user.getNickname());
                vo.setBelongPhoneNumber(PhoneNumberUtils.encPhoneNumber(user.getPhoneNumber()));
            }
            user = IdOperators.find(users, item.getGuideId());
            if(user != null){
                vo.setGuideNickname(user.getNickname());
                vo.setGuidePhoneNumber(PhoneNumberUtils.encPhoneNumber(user.getPhoneNumber()));
            }
            vo.setCarpoolTitle(carpool.getTitle());
            return vo;
        }).collect(Collectors.toList());
    }

    @Nullable
    @Override
    public Player select(@Nullable Long carpoolId, @Nullable Long userId) {
        if(carpoolId == null || userId == null){
            return null;
        }
        return mapper.selectPlayer(carpoolId, userId);
    }

    @Override
    public List<CarpoolPlayerCount> carpoolPlayerCounts(Collection<Long> carpoolIds) {
        if(CollectionUtils.isEmpty(carpoolIds)) {
            return Collections.emptyList();
        }
        carpoolIds = carpoolIds.stream().filter(Objects::nonNull).collect(Collectors.toSet());
        if(carpoolIds.isEmpty()){
            return Collections.emptyList();
        }
        return mapper.carpoolPlayerCounts(carpoolIds);
    }

    @Override
    public CarpoolReport customServicePlayerCountReport(Token token, CarpoolReport report) {
        Collection<Long> orgUnitIds = null;
        if(token.hasAuthority(RoleEnum.Admin)){
            //nothing
        }else if(token.hasAnyAuthority(RoleEnum.Manager, RoleEnum.ShopManager, RoleEnum.CarpoolMaster, RoleEnum.CustomerService)){
            orgUnitIds = new HashSet<>();
            orgUnitIntegration.userManageOrgUnits(token, orgUnitIds);
        }else{
            return report;
        }
        List<CarpoolReportCount> list = mapper.playerCountReport(orgUnitIds, report);
        List<SimpleOrgUnitVo> orgUnits = movieServiceInvoker.orgUnits(list.stream().map(CarpoolReportCount::getOrgUnitId).collect(Collectors.toSet()));
        List<SimpleUser> users = movieServiceInvoker.userInfo(list.stream().map(CarpoolReportCount::getUserId).collect(Collectors.toSet()));
        report.fillRecords(list,orgUnits, users);
        return report;
    }

    @Override
    public Long saveVirtualPlayer(Long carpoolId, Long userId) {
        Player entity = new Player();
        entity.setCarpoolId(carpoolId);
        entity.setUserId(userId);
        entity.setBelongId(-1L);
        entity.setJoinTime(new Date());
        entity.setGuideId(-1L);
        entity.setType(JoinPlayerParam.TYPE_VIRTUAL);
        insertSelective(entity);
        return entity.getId();
    }

    @Override
    public int updateRemark(Long id, String remark) {
        remark = StringUtils.trimToEmpty(remark);
        return update(id, "remark", remark);
    }
}
